#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "qisr.h"
#include "msp_cmn.h"
#include "msp_errors.h"
#include "speech_recognizer.h"
#include <iconv.h>

#include "ros/ros.h"
#include "myxfei/voiceSrv.h"

#define FRAME_LEN   640 
#define BUFFER_SIZE 4096

static void show_result(char *string, char is_over)
{  
    printf("\rI hear: %s ", string);
    if(is_over)
        putchar('\n');
}
 
static char *g_result = NULL;
static unsigned int g_buffersize = BUFFER_SIZE;
 
void on_result(const char *result, char is_last)
{
    if (result) {
        size_t left = g_buffersize - 1 - strlen(g_result);
        size_t size = strlen(result);
        if (left < size) {
            g_result = (char*)realloc(g_result, g_buffersize + BUFFER_SIZE);
            if (g_result)
                g_buffersize += BUFFER_SIZE;
            else {
                printf("mem alloc failed\n");
                return;
            }
        }
        strncat(g_result, result, size);
        show_result(g_result, is_last);
    }
}
 
void on_speech_begin()
{
    if (g_result)
    {
        free(g_result);
    }
    g_result = (char*)malloc(BUFFER_SIZE);
    g_buffersize = BUFFER_SIZE;
    memset(g_result, 0, g_buffersize);
 
    printf("Start Listening...\n");
}
void on_speech_end(int reason)
{
    if (reason == END_REASON_VAD_DETECT)
        printf("\nSpeaking done \n");
    else
        printf("\nRecognizer error %d\n", reason);
}
 
/* demo recognize the audio from microphone */
static void demo_mic(const char* session_begin_params)
{
    int errcode;
    int i = 0;
 
    struct speech_rec iat;
 
    struct speech_rec_notifier recnotifier = {
        on_result,
        on_speech_begin,
        on_speech_end
    };
 
    errcode = sr_init(&iat, session_begin_params, SR_MIC, &recnotifier);
    if (errcode) {
        printf("speech recognizer init failed\n");
        return;
    }
    errcode = sr_start_listening(&iat);
    if (errcode) {
        printf("start listen failed %d\n", errcode);
    }
    /* demo 10 seconds recording */
    while(i++ < 10)
        sleep(1);
    errcode = sr_stop_listening(&iat);
    if (errcode) {
        printf("stop listening failed %d\n", errcode);
    }
    sr_uninit(&iat);
}

char* GetName(char* str)
{
    //My name is ***.
	const char* word1 = "is ";
	int i,j;
	for(i = 0;i<strlen(str);i++)
	{
		for(j = 0;word1[j]&&(i+j)<strlen(str)&&word1[j] == str[i+j];j++);
		if(!word1[j])
		{
			i = i+j;
			for(j=0;str[j]&&(i+j)<strlen(str)&&str[i+j]!='.'&&str[i+j]!=' ';j++);
			char* name = (char*)malloc(j);
			strncpy(name,str+i,j);
            printf("%s\n",name);
			return name;
		}
	}
	return NULL;
}
char* GetThing(char* str)
{
    //Please bring me a **.
    const char* keyword = "me ";
    int i,j;
    int len = strlen(str);
    for(i = 0;i < len;i++)
    {
        for(j = 0;keyword[j] && (i+j) < len && keyword[j] == str[i+j];j++);
        if(!keyword[j])
        {
            //i=i+j;
            //for(j = 0;(i+j) < strlen(str) && str[i+j] != ' ';j++);
            //i = i+j+1;
            //for(j = 0;(i+j) < strlen(str) && str[i+j]!='.'&&str[i+j]!=' ';j++);
            j = i+j;
            for(;j < len && str[j] != '.' && str[j] != '?';j++)
            {
                if(str[j] == ' ')
                    i = j+1;
            }
            j = j-i;
            char* thing = (char*)malloc(j);
            strncpy(thing,str+i,j);
            printf("%s\n",thing);
            return thing;
        }
    }
    return NULL;
}
char* VoiceRecognition(bool type)
{
    /*
    type = 0 提取姓名
    type= 1 提取物品
    */

    int ret = MSP_SUCCESS;
    const char* login_params = "appid = 5e81ee6d, work_dir = .";

    const char* session_begin_params =
        "sub = iat, domain = iat, language = zh_cn, "
        "accent = mandarin, sample_rate = 16000, "
        "result_type = plain, result_encoding = utf8";

    ret = MSPLogin(NULL, NULL, login_params);
    if(MSP_SUCCESS != ret){
        MSPLogout();
        printf("MSPLogin failed , Error code %d.\n",ret);
    }

    printf("Speak in 10 seconds\n");
    demo_mic(session_begin_params);
    if(!type)
    {
        printf("get name : ");
        MSPLogout();
        return GetName(g_result);
    }
    else
    {
        printf("get thing : ");
        MSPLogout();
        return GetThing(g_result);
    }
    MSPLogout();
}

bool voiceServer(myxfei::voiceSrv::Request &req,myxfei::voiceSrv::Response &res)
{
    res.result = VoiceRecognition(req.type);
    ROS_INFO("recognition result: %s",res.result.c_str());
    return true;
}

int main(int argc, char* argv[])
{
    ros::init(argc,argv,"voice_recognition_service");
    ros::NodeHandle n;

    ros::ServiceServer voiceRgtService = n.advertiseService("voice_recognition_server",voiceServer);
    ROS_INFO("Ready to recognition voice.");
    ros::spin();
    return 0;
}